#include "networkconfig.h"
#include <QDateTime>
#include <QDebug>
#include <QtEndian>

NetworkConfig::NetworkConfig(QObject *parent)
    : QObject(parent)
    , tcpSocket(new QTcpSocket(this))
    , reconnectTimer(new QTimer(this))
    , currentState(DISCONNECTED)
    , reconnectAttempts(0)
{
    // 设置TCP套接字
    tcpSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
    tcpSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);

    // 连接信号槽
    connect(tcpSocket, &QTcpSocket::connected, this, &NetworkConfig::onConnected);
    connect(tcpSocket, &QTcpSocket::disconnected, this, &NetworkConfig::onDisconnected);
    connect(tcpSocket, &QTcpSocket::readyRead, this, &NetworkConfig::onReadyRead);

#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
    connect(tcpSocket, &QTcpSocket::errorOccurred, this, &NetworkConfig::onErrorOccurred);
#else
    connect(tcpSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
            this, &NetworkConfig::onErrorOccurred);
#endif

    // 配置重连定时器
    reconnectTimer->setInterval(3000); // 3秒重连
    reconnectTimer->setSingleShot(true);
    connect(reconnectTimer, &QTimer::timeout, this, &NetworkConfig::onReconnectTimeout);
}

NetworkConfig::~NetworkConfig()
{
    disconnectFromServer();
    tcpSocket->deleteLater();
}

void NetworkConfig::connectToServer(const QString &host, quint16 port)
{
    if (currentState == CONNECTED || currentState == CONNECTING) {
        qDebug() << "Already connected or connecting";
        return;
    }

    serverHost = host;
    serverPort = port;
    setConnectionState(CONNECTING);

    qDebug() << "Connecting to server:" << host << ":" << port;
    tcpSocket->connectToHost(host, port);
}

void NetworkConfig::disconnectFromServer()
{
    stopReconnectTimer();
    setConnectionState(DISCONNECTED);

    if (tcpSocket->state() != QAbstractSocket::UnconnectedState) {
        tcpSocket->disconnectFromHost();
    }

    receiveBuffer.clear();
    nextMessageSize = -1;
}

void NetworkConfig::sendRequest(const QString &command, const QJsonObject &params)
{
    if (currentState != CONNECTED) {
        emit errorOccurred("Not connected to server");
        return;
    }

    QMutexLocker locker(&sendMutex);

    RequestData request;
    request.command = command;
    request.params = params;
    request.timestamp = QDateTime::currentSecsSinceEpoch();

    QByteArray jsonData = serializeRequest(request);
    QByteArray message = serializeMessage(jsonData);

    if (tcpSocket->write(message) == -1) {
        emit errorOccurred("Failed to send data: " + tcpSocket->errorString());
    } else {
        tcpSocket->flush();
        qDebug() << "Sent request:" << command << "with params:" << params;
    }
}

NetworkConfig::ConnectionState NetworkConfig::connectionState() const
{
    return currentState;
}

bool NetworkConfig::isConnected() const
{
    return currentState == CONNECTED;
}

QByteArray NetworkConfig::serializeRequest(const RequestData &request) const
{
    QJsonObject jsonObj;
    jsonObj["cmd"] = request.command;
    jsonObj["params"] = request.params;
    jsonObj["ts"] = request.timestamp;

    return QJsonDocument(jsonObj).toJson(QJsonDocument::Compact);
}

NetworkConfig::ResponseData NetworkConfig::deserializeResponse(const QByteArray &jsonData) const
{
    ResponseData response;
    QJsonDocument doc = QJsonDocument::fromJson(jsonData);

    if (doc.isNull() || !doc.isObject()) {
        response.status = 500;
        response.message = "Invalid JSON format";
        return response;
    }

    QJsonObject json = doc.object();
    response.status = json.value("status").toInt(500);
    response.message = json.value("msg").toString("Unknown error");
    response.data = json.value("data").toObject();
    response.timestamp = json.value("ts").toInt();

    return response;
}

QByteArray NetworkConfig::serializeMessage(const QByteArray &data) const
{
    // 消息格式: 4字节长度(网络字节序) + 数据
    QByteArray message;
    qint32 length = data.size();
    QByteArray lengthBytes(4, 0);
    qToBigEndian<qint32>(length, reinterpret_cast<uchar*>(lengthBytes.data()));

    message.append(lengthBytes);
    message.append(data);
    return message;
}

void NetworkConfig::setConnectionState(ConnectionState state)
{
    if (currentState != state) {
        currentState = state;
        emit connectionStateChanged(state);

        if (state == CONNECTED) {
            emit connected();
        } else if (state == DISCONNECTED) {
            emit disconnected();
        }
    }
}

void NetworkConfig::startReconnectTimer()
{
    reconnectAttempts++;
    emit reconnecting(reconnectAttempts);
    reconnectTimer->start();
}

void NetworkConfig::stopReconnectTimer()
{
    reconnectTimer->stop();
    reconnectAttempts = 0;
}

void NetworkConfig::onConnected()
{
    qDebug() << "Connected to server";
    setConnectionState(CONNECTED);
    stopReconnectTimer();
}

void NetworkConfig::onDisconnected()
{
    qDebug() << "Disconnected from server";
    setConnectionState(DISCONNECTED);

    // 如果不是主动断开，尝试重连
    if (reconnectTimer->isActive() || currentState == RECONNECTING) {
        startReconnectTimer();
    }
}

void NetworkConfig::onReadyRead()
{
    receiveBuffer.append(tcpSocket->readAll());
    processBuffer();
}

void NetworkConfig::onErrorOccurred(QAbstractSocket::SocketError socketError)
{
    Q_UNUSED(socketError);

    QString errorStr = tcpSocket->errorString();
    qWarning() << "Network error:" << errorStr;
    emit errorOccurred(errorStr);

    // 如果连接失败，尝试重连
    if (currentState == CONNECTING || currentState == RECONNECTING) {
        startReconnectTimer();
    } else if (currentState == CONNECTED) {
        setConnectionState(RECONNECTING);
        startReconnectTimer();
    }
}

void NetworkConfig::onReconnectTimeout()
{
    qDebug() << "Attempting to reconnect... Attempt" << reconnectAttempts;
    setConnectionState(RECONNECTING);
    tcpSocket->connectToHost(serverHost, serverPort);
}

void NetworkConfig::processBuffer()
{
    while (true) {
        // 如果还不知道消息长度，先尝试读取4字节
        if (nextMessageSize == -1) {
            if (receiveBuffer.size() < 4) {
                return; // 等待更多数据
            }

            // 读取长度 (网络字节序)
            nextMessageSize = qFromBigEndian<qint32>(receiveBuffer.left(4).constData());
            receiveBuffer.remove(0, 4);
        }

        // 检查是否已经接收到完整消息
        if (receiveBuffer.size() < nextMessageSize) {
            return; // 等待更多数据
        }

        // 提取消息数据
        QByteArray jsonData = receiveBuffer.left(nextMessageSize);
        receiveBuffer.remove(0, nextMessageSize);
        nextMessageSize = -1; // 重置为-1，准备读取下一条消息

        // 解析JSON
        ResponseData response = deserializeResponse(jsonData);
        qDebug() << "Received response:"
                 << "Status:" << response.status
                 << "Message:" << response.message;
        emit responseReceived(response);
    }
}
